module spsr(
  input         clk,
  input  [ 3:0] we,
  input  [31:0] d,
  input  [ 4:0] mode,
  output [31:0] q,
  input  [ 4:0] alt_mode_w,
  input         w_alt_mode
);

reg [31:0] q_fiq;
reg [31:0] q_irq;
reg [31:0] q_svc;
reg [31:0] q_abt;
reg [31:0] q_und;

wire fiq;
wire irq;
wire svc;
wire abt;
wire und;

wire fiq_alt;
wire irq_alt;
wire svc_alt;
wire abt_alt;
wire und_alt;

assign q =
  {32{fiq}} & q_fiq |
  {32{irq}} & q_irq |
  {32{svc}} & q_svc |
  {32{abt}} & q_abt |
  {32{und}} & q_und ;

always @(posedge clk) begin
  if (w_alt_mode ? fiq_alt : fiq) begin
    if (we[3]) q_fiq[31:24] <= d[31:24];
    if (we[2]) q_fiq[23:16] <= d[23:16];
    if (we[1]) q_fiq[15: 8] <= d[15: 8];
    if (we[0]) q_fiq[ 7: 0] <= d[ 7: 0];
  end
  if (w_alt_mode ? irq_alt : irq) begin
    if (we[3]) q_irq[31:24] <= d[31:24];
    if (we[2]) q_irq[23:16] <= d[23:16];
    if (we[1]) q_irq[15: 8] <= d[15: 8];
    if (we[0]) q_irq[ 7: 0] <= d[ 7: 0];
  end
  if (w_alt_mode ? svc_alt : svc) begin
    if (we[3]) q_svc[31:24] <= d[31:24];
    if (we[2]) q_svc[23:16] <= d[23:16];
    if (we[1]) q_svc[15: 8] <= d[15: 8];
    if (we[0]) q_svc[ 7: 0] <= d[ 7: 0];
  end
  if (w_alt_mode ? abt_alt : abt) begin
    if (we[3]) q_abt[31:24] <= d[31:24];
    if (we[2]) q_abt[23:16] <= d[23:16];
    if (we[1]) q_abt[15: 8] <= d[15: 8];
    if (we[0]) q_abt[ 7: 0] <= d[ 7: 0];
  end
  if (w_alt_mode ? und_alt : und) begin
    if (we[3]) q_und[31:24] <= d[31:24];
    if (we[2]) q_und[23:16] <= d[23:16];
    if (we[1]) q_und[15: 8] <= d[15: 8];
    if (we[0]) q_und[ 7: 0] <= d[ 7: 0];
  end
end

/* verilator lint_off PINCONNECTEMPTY */
mode_decoder mode_decoder(
  .i_mode(mode),
  .o_usrbank(),
  .o_fiqbank(fiq),
  .o_irqbank(irq),
  .o_svcbank(svc),
  .o_abtbank(abt),
  .o_undbank(und)
);
/* verilator lint_on PINCONNECTEMPTY */

/* verilator lint_off PINCONNECTEMPTY */
mode_decoder alt_mode_decoder(
  .i_mode(alt_mode_w),
  .o_usrbank(),
  .o_fiqbank(fiq_alt),
  .o_irqbank(irq_alt),
  .o_svcbank(svc_alt),
  .o_abtbank(abt_alt),
  .o_undbank(und_alt)
);
/* verilator lint_on PINCONNECTEMPTY */

endmodule
